/**
 * @file utilities.c
 * @brief 
 * @author Gavin (420260138@qq.com)
 * @version 1.0
 * @date 2020-07-20
 * 
 * @copyright Copyright (c) {2020}  Gavin.Hsu
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of Apache License Version 2.0
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2020-07-20 <td>1.0     <td>Gavin     <td>create
 * </table>
 */
 #include <stdlib.h>
 #include "xconfig.h"
 #include "xtypes.h"
 #include "platform.h"
 
/**
 * @brief dump data of a block of memory
 * @param  msg              message
 * @param  data             pointer to dump data 
 * @param  size             dump data length in bytes
 */
void xMemDump( const char * msg, unsigned char * data, size_t size )
{
    int i;

    xMemInfoPrintf( "%s (%lu):", msg, size );
    for( i = 0 ; i < size ; i++ )
    {
        if( i % 8 == 0 ){
            if( i % 16 == 0 ){
                xMemInfoPrintf( "\r\n" );
            }else{
                xMemInfoPrintf( "\t" );
            }
        }

        xMemInfoPrintf( "%02x", data[i] );
    }
    xMemInfoPrintf( "\r\n" );
}


#if XMEM_HEADER_DIVIDE
/**
 * @brief dump xMem Management Header List
 * @param  xMemHdrLst       xMem Management Header List to dump
 */
void xMemMgrHdrListInfoDump( pxMemMgrHdr xMemHdrLst )
{
    pxMemMgrHdr phdrlst;

    phdrlst = xMemHdrLst;
    #if XMEM_CPU_64BIT == 1
    xMemInfoPrintf( "----------------------xMemMgrHdrLst Info------------------------\r\n" );
    xMemInfoPrintf( "|     Header         | HeaderSize  |      NextHeader    | Type |\r\n" );
    xMemInfoPrintf( "----------------------------------------------------------------\r\n" );
    while(phdrlst)
    {
        xMemInfoPrintf( "| 0x%016llx |   0x%04x    | 0x%016llx | 0x%02x |\r\n",
                ( AddressType ) phdrlst, phdrlst->size, ( AddressType ) phdrlst->next, phdrlst->type );
        phdrlst = phdrlst->next;
    }
    xMemInfoPrintf("----------------------------------------------------------------\r\n");
    #else
    xMemInfoPrintf( "--------------xMemMgrHdrLst Info----------------\r\n" );
    xMemInfoPrintf( "|   Header   | HeaderSize  | NextHeader | Type |\r\n" );
    xMemInfoPrintf( "------------------------------------------------\r\n" );
    while(phdrlst)
    {
        xMemInfoPrintf( "| 0x%08x |   0x%04x    | 0x%08x | 0x%02x |\r\n",
                (AddressType)phdrlst, phdrlst->size, (AddressType)phdrlst->next, phdrlst->type );
        phdrlst = phdrlst->next;
    }
    xMemInfoPrintf( "------------------------------------------------\r\n" );    
    #endif // end of XMEM_CPU_64BIT
    return;
}
#endif // end of XMEM_HEADER_DIVIDE

#if XMEM_SUPERBLOCK_SUPPORT
/**
 * @brief  dump xMem superblock list
 * @param  xMemSupBlkLst    xMem Superblock List to dump
 * @param  len              xMem Superblock List length
 */
void xMemSuperBlockInfoDump(xMemSuperBlock ** xMemSupBlkLst, int len)
{
    int i;
    xMemSuperBlock * psuperblock;

    #if XMEM_CPU_64BIT == 1
    xMemInfoPrintf( "------------------------------SuperBlock Info--------------------------------\r\n" );
    xMemInfoPrintf( "|   SupBlockHeader   | SupBlockSize | FreeNb  | Total  |        RamAddr     |\r\n" );
    xMemInfoPrintf( "-----------------------------------------------------------------------------\r\n" );   
    for( i = 0 ; i < len ; i++ )
    {
        psuperblock = xMemSupBlkLst[i];
        while(psuperblock)
        {
            xMemInfoPrintf("| 0x%016llx |   0x%04x     |  0x%02x   |  0x%02x  | 0x%016llx |\r\n",
                        ( AddressType ) psuperblock, psuperblock->cellsize, psuperblock->nfree, psuperblock->ncell, ( AddressType ) psuperblock->addr );
            psuperblock = psuperblock->next;
        }
    }
    xMemInfoPrintf( "-----------------------------------------------------------------------------\r\n" );
    #else
    xMemInfoPrintf( "-----------------------SuperBlock Info-------------------------\r\n" );
    xMemInfoPrintf( "|SupBlockHeader| SupBlockSize | FreeNb  | Total  |   RamAddr  |\r\n" );
    xMemInfoPrintf( "---------------------------------------------------------------\r\n" );   
    for( i = 0 ; i < len ; i++ )
    {
        psuperblock = xMemSupBlkLst[i];
        while( psuperblock )
        {
            xMemInfoPrintf( "|  0x%08x  |   0x%04x     |  0x%02x   |  0x%02x  | 0x%08x |\r\n",
                        ( AddressType ) psuperblock, psuperblock->cellsize, psuperblock->nfree, psuperblock->ncell, ( AddressType ) psuperblock->addr );
            psuperblock = psuperblock->next;
        }
    }
    xMemInfoPrintf( "---------------------------------------------------------------\r\n" );    
    #endif // end of XMEM_CPU_64BIT
}
#endif //end of XMEM_SUPERBLOCK_SUPPORT


/**
 * @brief dump xMem block list
 * @param  xMemBlkLst       xMem Block List to dump
 */
void xMemBlockListInfoDump( pxMemBlock xMemBlkLst )
{
    pxMemBlock pmemblk;

    pmemblk = xMemBlkLst;

    #if XMEM_CPU_64BIT == 1
    xMemInfoPrintf( "----------------------------Block Info-------------------------------\r\n" );
    xMemInfoPrintf( "|    Block           |   BlockSize   |     NextBlock       | IsFree |\r\n" );
    xMemInfoPrintf( "---------------------------------------------------------------------\r\n" );    
    while(pmemblk)
    {
        #if XMEM_HEADER_DIVIDE
        xMemInfoPrintf( "| 0x%016llx |  0x%08x   |  0x%016llx |  0x%02x  |\r\n", (AddressType) pmemblk->addr, pmemblk->blksize, ( AddressType ) pmemblk->next, pmemblk->free );
        #else        
        xMemInfoPrintf( " 0x%016llx |  0x%08x   |  0x%016llx |  0x%02x  |\r\n", (AddressType) pmemblk, pmemblk->blksize, ( AddressType ) pmemblk->next, pmemblk->free );
        #endif // end of XMEM_HEADER_DIVIDE
        pmemblk=pmemblk->next;
    }
    xMemInfoPrintf( "---------------------------------------------------------------------\r\n" );
    #else
    xMemInfoPrintf( "--------------------Block Info-----------------------\r\n" );
    xMemInfoPrintf( "|   Block    |   BlockSize   |  NextBlock  | IsFree |\r\n" );
    xMemInfoPrintf( "-----------------------------------------------------\r\n" );    
    while( pmemblk )
    {
        #if XMEM_HEADER_DIVIDE
        xMemInfoPrintf( "| 0x%08x |  0x%08x   |  0x%08x |  0x%02x  |\r\n", ( AddressType ) pmemblk->addr, pmemblk->blksize, ( AddressType ) pmemblk->next, pmemblk->free );
        #else        
        xMemInfoPrintf( " 0x%08x  |  0x%08x   |  0x%08x |  0x%02x  |\r\n", ( AddressType ) pmemblk, pmemblk->blksize, ( AddressType ) pmemblk->next, pmemblk->free );
        #endif //end of XMEM_HEADER_DIVIDE
        pmemblk = pmemblk->next;
    }
    xMemInfoPrintf( "-----------------------------------------------------\r\n" );    
    #endif// end of XMEM_CPU_64BIT
    return;
}
